package com.modbus.tcp.controller;

import com.modbus.tcp.domain.*;
import com.modbus.tcp.service.*;
import com.modbus.tcp.utils.*;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
//import com.sun.javaws.exceptions.ExitException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//import java.nio.ByteBuffer;
//import java.nio.ShortBuffer;
//import java.text.SimpleDateFormat;
import java.sql.Struct;
import java.util.*;


/**
 * @Author: lxd
 * @Date: 2022/11/7 18:07
 */

@Slf4j
@RestController
@EnableAsync
@RequestMapping("/modbus-tcp")
public class ModbusTcpController {

    @Autowired
    private Modbus4jWriter modbus4jWriter;

    @Autowired
    private Modbus4jReader modbus4jReader;

    @Autowired
    private Modbus4jTcpMaster modbus4jTcpMaster;

    @Autowired
    private IModbusslaveService modbusslaveService;
    @Autowired
    private Modbusslave modbusslave;

    @Autowired
    private IBallvalveaddrService ballvalveaddrService;
    //    @Autowired

    @Autowired
    private IFiberhoststatusService fiberhoststatusService;

    private Fiberhoststatus fiberhoststatus = new Fiberhoststatus();

    @Autowired
    private IFiberhostchannelService fiberhostchannelService;

    private Fiberhostchannel fiberhostchannel;


    @Autowired
    private IFiberhostpartService fiberhostpartService;

    private Fiberhostpart fiberhostpart;


    @Autowired
    private ISensortypeService sensortypeService;
    private Sensortype sensortype;

    @Autowired
    private IFiberhostparthistoryService fiberhostparthistoryService;
    private Fiberhostparthistory fiberhostparthistory;

    @Autowired
    private IBallvalvedataService ballvalvedataService;


    private ModbusMaster modbusMaster;


    /**
     *  该方法为
     *  一、设备开机后，遍历所有的modbus服务器上所连接的所有球阀设备
     *      1、不在线。（dataarea 设为-1，）
     *      2、在线
     *
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     * @throws ModbusInitException
     * @author
     * @date
     */

    @Scheduled(fixedDelay = 5 * 1000)
    public void readHoldingRegister() throws ModbusTransportException, ErrorResponseException, ModbusInitException {

        //查询所有的modbus设备
        List<Modbusslave> list = modbusslaveService.selectModbusslaveList(modbusslave);
        for (Modbusslave modbusslave1 : list) {
            try {
                //创建modbus对象
                ModbusMaster modbusMaster = modbus4jTcpMaster.getMaster(modbusslave1.getHostaddr(), modbusslave1.getPort(), false);
                Ballvalveaddr ballvalveaddr1 = new Ballvalveaddr();
                ballvalveaddr1.setModbusid(modbusslave1.getModbusid());
                //查找该485服务器通道上的所有球阀设备
                List<Ballvalveaddr> list2 = ballvalveaddrService.selectBallvalveaddrList(ballvalveaddr1);
                for (Ballvalveaddr ballvalveaddrOld : list2) {
                    System.out.println("球阀的modbus地址："+ballvalveaddrOld.getSlaveaddr());
                    try {
//                        Ballvalveaddr ballvalveaddrNew = ballvalveaddrService.selectBallvalveaddrById(ballvalveaddrOld.getBallvalueid());
                        //485服务器（指定通道）不在线，将球阀状态设为离线
                        if (!modbusMaster.isInitialized()) {
                            ballvalveaddrOld.setFunctioncode(3);
                            //-1表示球阀设备不在线（或者485通信服务器没有连接）
                            ballvalveaddrOld.setDataarea("-1");
                            Date date = new Date();
                            ballvalveaddrOld.setDatadate(date);
                            ballvalveaddrService.updateBallvalveaddr(ballvalveaddrOld);
                            continue;
                        }
                        //设备在线
                        if (ballvalveaddrOld.getFunctioncode() == 3) {
                            //读球阀数据
                            short[] shorts = modbus4jReader.readHoldingRegister1(modbusMaster, ballvalveaddrOld.getSlaveaddr(), ballvalveaddrOld.getDataaddr(), ballvalveaddrOld.getDatalen());

                            if (shorts != null) {
                                System.out.println("读modbus地址的球阀："+ballvalveaddrOld.getSlaveaddr()+"，数据：" +Arrays.toString(shorts));
                                ballvalveaddrOld.setDataarea(HexUtils.Shorts2String(shorts));
                                Date date = new Date();
                                ballvalveaddrOld.setDatadate(date);
                                ballvalveaddrService.updateBallvalveaddr(ballvalveaddrOld);
                            } else {
                                System.out.println("读modbus地址的球阀："+ballvalveaddrOld.getSlaveaddr()+"，没有数据：" +Arrays.toString(shorts));
                                //当前时间与配置时间差如果大于3秒,说明为离线
                                if (((new Date()).getTime() - ballvalveaddrOld.getDatadate().getTime()) / (1000) > 3) {
                                    ballvalveaddrOld.setDataarea("-1");
                                    Date date = new Date();
                                    ballvalveaddrOld.setDatadate(date);
                                    ballvalveaddrService.updateBallvalveaddr(ballvalveaddrOld);
                                }
                            }

                        } else if (ballvalveaddrOld.getFunctioncode() == 6) {
                            //如果为写数据（这里只有球阀需要写数据）
                            //给球阀写数据slaveaddr为球阀485地址，dataaddr为寄存器地址，数据21为打开声光，20为关闭声光
                            boolean writerOK = modbus4jWriter.writeRegister1(modbusMaster, ballvalveaddrOld.getSlaveaddr(),ballvalveaddrOld.getDataaddr(), Short.valueOf(ballvalveaddrOld.getDataarea()));
                            if (writerOK) {

                                //Thread.sleep(10000);
                                //写完数据将状态改为读（3读6写）
                                ballvalveaddrOld.setFunctioncode(3);
                                Date date = new Date();
                                short[] shorts = modbus4jReader.readHoldingRegister1(modbusMaster, ballvalveaddrOld.getSlaveaddr(), ballvalveaddrOld.getDataaddr(), ballvalveaddrOld.getDatalen());
                                if (shorts != null) {
                                    System.out.println("读modbus地址的球阀："+ballvalveaddrOld.getSlaveaddr()+"，数据：" +Arrays.toString(shorts));
                                    ballvalveaddrOld.setDataarea(HexUtils.Shorts2String(shorts));
                                    ballvalveaddrOld.setDatadate(date);
                                    ballvalveaddrService.updateBallvalveaddr(ballvalveaddrOld);
                                } else {
                                    //
                                    if (((new Date()).getTime() - ballvalveaddrOld.getDatadate().getTime()) / (1000) > 3) {
                                        ballvalveaddrOld.setDataarea("-1");
                                        ballvalveaddrOld.setDatadate(date);
                                        ballvalveaddrService.updateBallvalveaddr(ballvalveaddrOld);
                                    }

                                }
                            }


                        }
                    } catch (ModbusTransportException e) {
                        //这个报错说明为球阀没有连接
                        //-1表示球阀设备不在线（或者485通信服务器没有连接）
                        ballvalveaddrOld.setDataarea("-1");
                        ballvalveaddrOld.setFunctioncode(3);
                        Date date = new Date();
                        ballvalveaddrOld.setDatadate(date);
                        ballvalveaddrService.updateBallvalveaddr(ballvalveaddrOld);
                        System.out.println("球阀没有连接上==========，");

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            } catch (Exception e) {
                log.error(e.toString());
            }finally {
                if (modbusMaster != null) {
                    modbusMaster.setConnected(false);
                    modbusMaster.destroy();
                }

            }
        }


        log.info("======================ballvalveaddrController,球阀数据更新定时器");

        //查找所有分区的球阀设备
        List<Ballvalveaddr> listBall = ballvalveaddrService.allBallvalveaddr();
        for(Ballvalveaddr ballvalveaddr : listBall) {
            //当球阀状态为读状态
            if(ballvalveaddr.getFunctioncode() == 3) {
                Ballvalvedata ballvalvedata = new Ballvalvedata();
                ballvalvedata.setBallvalueid(ballvalveaddr.getBallvalueid());
                ballvalvedata.setId(ballvalveaddr.getId());
                ballvalvedata.setPartcode(ballvalveaddr.getPartcode());
                //-1为球阀离线状态
                if (ballvalveaddr.getDataarea().toString().equals("-1")) {
                    for (int i = 1; i <= 6; i++) {
                        //默认球阀有6个寄存器
                        ballvalvedata.setChannelcode(i);
                        List<Ballvalvedata> list3 = ballvalvedataService.selectBallvalvedataList(ballvalvedata);
                        if (list3.size() > 0) {
                            //球阀寄存器数据（6个）存在则更新
                            if(i>0){
                                Ballvalvedata ballvalvedataOne = list3.get(0);
                                ballvalvedataOne.setSensorvalue(-1f);
                                ballvalvedataOne.setDatadate(new Date());
                                ballvalvedataService.updateBallvalvedata(ballvalvedataOne);
                            }
                        } else {
                            //球阀寄存器数据（6个）不存在则新增
                            Ballvalvedata ballvalvedataTwo = new Ballvalvedata();
                            ballvalvedataTwo.setBallvalueid(ballvalveaddr.getBallvalueid());
                            ballvalvedataTwo.setId(ballvalveaddr.getId());
                            ballvalvedataTwo.setPartcode(ballvalveaddr.getPartcode());
                            ballvalvedataTwo.setName(ballvalveaddr.getName());
                            ballvalvedataTwo.setChannelcode(i);
                            if(i>0) {

                                ballvalvedata.setSensorvalue(-1f);
                            }
                            ballvalvedata.setDatadate(new Date());
                            ballvalvedataService.insertBallvalvedata(ballvalvedata);
                        }
                    }
                } else {
                    //球阀为在线状态且为读状态则将对应数据更新到球阀寄存器信息中
                    String[] dataarray = Convert.toStrArray(ballvalveaddr.getDataarea());
                    for (int i = 1; i <= dataarray.length; i++) {

                        ballvalvedata.setChannelcode(i);
                        //查询球阀6个寄存器的数据
                        List<Ballvalvedata> list3 = ballvalvedataService.selectBallvalvedataList(ballvalvedata);
                        if (list3.size() > 0) {
                            if(i>0) {
                                Ballvalvedata ballvalvedataThree = list3.get(0);
                                ballvalvedataThree.setSensorvalue(Convert.toFloat(dataarray[i-1]));
                                ballvalvedataThree.setDatadate(new Date());
                                ballvalvedataService.updateBallvalvedata(ballvalvedataThree);
                            }
                        } else {

                            Ballvalvedata ballvalvedataFour = new Ballvalvedata();
                            //球阀的id
                            ballvalvedataFour.setBallvalueid(ballvalveaddr.getBallvalueid());
                            ballvalvedataFour.setId(ballvalveaddr.getId());
                            //球阀的分区编号
                            ballvalvedataFour.setPartcode(ballvalveaddr.getPartcode());
                            //球阀的分区名称
                            ballvalvedataFour.setName(ballvalveaddr.getName());
                            //寄存器编号
                            ballvalvedataFour.setChannelcode(i);
                            if(i>0) {
                                //寄存器的数据
                                ballvalvedataFour.setSensorvalue(Convert.toFloat(dataarray[i-1]));
                            }
                            ballvalvedataFour.setDatadate(new Date());
                            ballvalvedataService.insertBallvalvedata(ballvalvedataFour);
                        }
                    }

                }
            }
        }

        //下面部分为原有的光纤测温主机的代码
        //------------------------------------------------------------------------------------------------------------

        log.info("======================测温主机的定时modbus定时任务");
        //最大值
        float Tempmax = 80;
        //查询传感器类型为8，8为光纤
        sensortype = sensortypeService.selectSensortypeById(8);
        if (sensortype != null) {
            Tempmax = sensortype.getAlarmvalue();
        }
        //查询所有的测温光纤主机
        List<Fiberhoststatus> list1 = fiberhoststatusService.selectFiberhoststatusList(fiberhoststatus);
        for (Fiberhoststatus fiberhoststatus : list1) {
            try {
                //创建modbus对象
                if (modbusMaster == null) {
                    modbusMaster = modbus4jTcpMaster.getMaster(fiberhoststatus.getHostIp(), fiberhoststatus.getHostport(), false);
                }

                if (!modbusMaster.isInitialized()) {
                    modbusMaster = null;
                    continue;
                }
                //modbus对象读数据（读取2个寄存器，第一个为主机状态，第二个为主机的通道数）
                short[] shorts = modbus4jReader.readHoldingRegister1(modbusMaster, Integer.parseInt(fiberhoststatus.getModbusAddr()), 1, 2);
                if (shorts != null) {
                    //设置测温主机的状态
                    fiberhoststatus.setHoststatus(Convert.toInt(shorts[0]));
                    Date date = new Date();
                    fiberhoststatus.setDatadate(date);
                    //设置测温主机的通道数
                    fiberhoststatus.setChannelsum(Convert.toInt(shorts[1]));
                    fiberhoststatusService.updateFiberhoststatus(fiberhoststatus);
                }
                //测温主机的通道等状态对象
                fiberhostchannel = new Fiberhostchannel();
                fiberhostchannel.setFiberhostid(fiberhoststatus.getFiberhostid());
                //查出数据库配置的测温主机的所有通道
                List<Fiberhostchannel> list2 = fiberhostchannelService.selectFiberhostchannelList(fiberhostchannel);
                int channel1addr = 21; //21表示通道信息的寄存器从21开始，一共有8个寄存器（每个通道）
                for (Fiberhostchannel fiberhostchannel : list2) {
                    short[] shorts2 = new short[8];
                    //默认读取数据时的通道与地址转换关系
                    int channeladdr = channel1addr + (fiberhostchannel.getChannelcode() - 1) * 8;
                    // 读取测温主机的数据
                    shorts2 = modbus4jReader.readHoldingRegister1(modbusMaster, Integer.parseInt(fiberhoststatus.getModbusAddr()), channeladdr, 8);
                    if (shorts2 != null) {

                        fiberhostchannel.setFiberquality(Convert.toInt(shorts2[0]));
                        fiberhostchannel.setPartsum(Convert.toInt(shorts2[1]));
                        fiberhostchannel.setChannellen(Convert.toInt(shorts2[2]));
                        fiberhostchannel.setFirealarm(Convert.toInt(shorts2[3]));
                        fiberhostchannel.setFiberalarm(Convert.toInt(shorts2[4]));
                        Date date = new Date();
                        fiberhostchannel.setDatadate(date);
                        fiberhostchannelService.updateFiberhostchannel(fiberhostchannel);
                    }
                    int partcode1addr = 200; //对应通道下的分区信息的寄存器从200开始
                    //遍历测温主机通道下的分区（partSum为分区数量）
                    for (int i = 1; i <= fiberhostchannel.getPartsum(); i++) {
                        fiberhostpart = new Fiberhostpart();
                        fiberhostpart.setChannelid(fiberhostchannel.getChannelcode());
                        fiberhostpart.setPartcode(i);
                        List<Fiberhostpart> list3 = fiberhostpartService.selectFiberhostpartList(fiberhostpart); //指定测温主机的指定通道信息
                        short[] shorts3 = new short[8];
                        // 通道下的各个分区与寄存器地址的转换（partcodeaddr为通道下的分区寄存器地址）
                        int partcodeaddr = (fiberhostchannel.getChannelcode() - 1) * 1000 + partcode1addr + (i - 1) * 8;
                        shorts3 = modbus4jReader.readHoldingRegister1(modbusMaster, Integer.parseInt(fiberhoststatus.getModbusAddr()), partcodeaddr, 8); //读取到通道下指定分区的数据
                        fiberhostparthistory = new Fiberhostparthistory(); //测温主机通道下的各个分区的温度信息
                        //更新光纤测温主机每个分区信息(通过)
                        if (list3.size() > 0) {
                            Fiberhostpart fiberhostpart = list3.get(0); //通道下的指定分区的信息
                            Float lstempmax = fiberhostpart.getTempmax();
                            if (shorts3 != null) {
                                fiberhostpart.setAlarmstatus(Convert.toInt(shorts3[0]));//报警状态(0-无报警1-定温2-差温-3预报警)
                                fiberhostpart.setAlarmvalue(Convert.toFloat((shorts3[1] * 0.01 - 200) > 0 ? (shorts3[1] * 0.01 - 200) : 0));//报警阈值(对应报警状态)
                                fiberhostpart.setAlarmloc(Convert.toFloat(shorts3[2]));//报警位置（对应米标）
                                fiberhostpart.setTempmax(Convert.toFloat((shorts3[3] * 0.01 - 200) > 0 ? (shorts3[3] * 0.01 - 200) : 0));//实时最高温度
                                fiberhostpart.setTempmaxloc(Convert.toFloat(shorts3[4]));//实时最高温度位置
                                fiberhostpart.setTempavg(Convert.toFloat((shorts3[5] * 0.01 - 200) > 0 ? (shorts3[5] * 0.01 - 200) : 0));//实时分区平均值
                                Date date = new Date();
                                fiberhostpart.setDatadate(date);
                                fiberhostpartService.updateFiberhostpart(fiberhostpart); //更新通道下指定分区的温度信息

                                if (Math.abs(lstempmax - fiberhostpart.getTempmax()) > 2) { //保存历史数据
                                    fiberhostparthistory.setCompanyname("");
                                    fiberhostparthistory.setId(fiberhostchannel.getId());
                                    fiberhostparthistory.setStopfilename(fiberhostchannel.getStopfilename());
                                    fiberhostparthistory.setHostname(fiberhoststatus.getHostname());
                                    fiberhostparthistory.setHostIp(fiberhoststatus.getHostIp());
                                    fiberhostparthistory.setHostport(fiberhoststatus.getHostport());
                                    fiberhostparthistory.setChannelcode(fiberhostchannel.getChannelcode());
                                    fiberhostparthistory.setPartcode(fiberhostpart.getPartcode());
                                    fiberhostparthistory.setAlarmstatus(fiberhostpart.getAlarmstatus());
                                    fiberhostparthistory.setAlarmvalue(fiberhostpart.getAlarmvalue());
                                    fiberhostparthistory.setAlarmloc(fiberhostpart.getAlarmloc());
                                    fiberhostparthistory.setTempmax(fiberhostpart.getTempmax());
                                    fiberhostparthistory.setTempmaxloc(fiberhostpart.getTempmaxloc());
                                    fiberhostparthistory.setTempavg(fiberhostpart.getTempavg());
                                    fiberhostparthistory.setDatadate(new Date());
                                    fiberhostparthistoryService.insertFiberhostparthistory(fiberhostparthistory);
                                }
                            }
                        } else {
                            Fiberhostpart fiberhostpart = new Fiberhostpart();//没有则新增通道下的分区信息
                            if (shorts3 != null) {
                                fiberhostpart.setChannelid(fiberhostchannel.getChannelid());
                                fiberhostpart.setPartcode(i);
                                fiberhostpart.setAlarmstatus(Convert.toInt(shorts3[0]));
                                fiberhostpart.setAlarmvalue(Convert.toFloat((shorts3[1] * 0.01 - 200) > 0 ? (shorts3[1] * 0.01 - 200) : 0));
                                fiberhostpart.setAlarmloc(Convert.toFloat(shorts3[2]));
                                fiberhostpart.setTempmax(Convert.toFloat((shorts3[3] * 0.01 - 200) > 0 ? (shorts3[3] * 0.01 - 200) : 0));
                                fiberhostpart.setTempmaxloc(Convert.toFloat(shorts3[4]));
                                fiberhostpart.setTempavg(Convert.toFloat((shorts3[5] * 0.01 - 200) > 0 ? (shorts3[5] * 0.01 - 200) : 0));
                                Date date = new Date();
                                fiberhostpart.setDatadate(date);
                                fiberhostpartService.insertFiberhostpart(fiberhostpart);

                                fiberhostparthistory.setCompanyname("");
                                fiberhostparthistory.setId(fiberhostchannel.getId());
                                fiberhostparthistory.setStopfilename(fiberhostchannel.getStopfilename());
                                fiberhostparthistory.setHostname(fiberhoststatus.getHostname());
                                fiberhostparthistory.setHostIp(fiberhoststatus.getHostIp());
                                fiberhostparthistory.setHostport(fiberhoststatus.getHostport());
                                fiberhostparthistory.setChannelcode(fiberhostchannel.getChannelcode());
                                fiberhostparthistory.setPartcode(fiberhostpart.getPartcode());
                                fiberhostparthistory.setAlarmstatus(fiberhostpart.getAlarmstatus());
                                fiberhostparthistory.setAlarmvalue(fiberhostpart.getAlarmvalue());
                                fiberhostparthistory.setAlarmloc(fiberhostpart.getAlarmloc());
                                fiberhostparthistory.setTempmax(fiberhostpart.getTempmax());
                                fiberhostparthistory.setTempmaxloc(fiberhostpart.getTempmaxloc());
                                fiberhostparthistory.setTempavg(fiberhostpart.getTempavg());
                                fiberhostparthistory.setDatadate(new Date());
                                fiberhostparthistoryService.insertFiberhostparthistory(fiberhostparthistory);
                            }
                        }
                        //这是打开球阀的逻辑
                        if (shorts3 != null) {
                            if (Convert.toFloat(shorts3[3] * 0.01 - 200) > Tempmax) {
                                //应该打开光纤通道分区对应分区的球阀
                                //第一步，找见光纤通道分区对应的球阀modbus主机地址fiberhostchannel.getId()(安装位置的id)
                                Ballvalveaddr ballvalveaddr = ballvalveaddrService.selectBallvalveByPartcode(fiberhostchannel.getId(), i);
                                if (ballvalveaddr != null) {
                                    ballvalveaddr.setFunctioncode(6);
                                    ballvalveaddr.setDataarea("11");
                                    Date date = new Date();
                                    ballvalveaddr.setDatadate(date);
                                    ballvalveaddrService.updateBallvalveaddr(ballvalveaddr);
                                }
                            }
                        }
                    }
                }

            } catch (Exception e) {
                log.error("{}测温主机异常",fiberhoststatus.getHostIp());

            }finally {
                //关闭modbus连接
                if (modbusMaster != null) {
                    modbusMaster.setConnected(false);
                    modbusMaster.destroy();
                }

            }
        }

    }


    /**
     *
     * 测温主机相关逻辑
     * @return
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     * @throws ModbusInitException
     * @author
     * @date
     */

//    @Scheduled(fixedDelay = 5 * 1000)
    public void readInputRegisters() throws ModbusTransportException, ErrorResponseException, ModbusInitException {

        log.info("======================测温主机的定时modbus定时任务");
        //最大值
        float Tempmax = 80;
        //查询传感器类型为8，8为光纤
        sensortype = sensortypeService.selectSensortypeById(8);
        if (sensortype != null) {
            Tempmax = sensortype.getAlarmvalue();
        }
        //查询所有的测温光纤主机
        List<Fiberhoststatus> list = fiberhoststatusService.selectFiberhoststatusList(fiberhoststatus);
        for (Fiberhoststatus fiberhoststatus : list) {
            try {
                //创建modbus对象
                if (modbusMaster == null) {
                    modbusMaster = modbus4jTcpMaster.getMaster(fiberhoststatus.getHostIp(), fiberhoststatus.getHostport(), false);
                }

                if (!modbusMaster.isInitialized()) {
                    modbusMaster = null;
                    continue;
                }
                //modbus对象读数据（读取2个寄存器，第一个为主机状态，第二个为主机的通道数）
                short[] shorts = modbus4jReader.readHoldingRegister1(modbusMaster, Integer.parseInt(fiberhoststatus.getModbusAddr()), 1, 2);
                if (shorts != null) {
                    //设置测温主机的状态
                    fiberhoststatus.setHoststatus(Convert.toInt(shorts[0]));
                    Date date = new Date();
                    fiberhoststatus.setDatadate(date);
                    //设置测温主机的通道数
                    fiberhoststatus.setChannelsum(Convert.toInt(shorts[1]));
                    fiberhoststatusService.updateFiberhoststatus(fiberhoststatus);
                }
                //测温主机的通道等状态对象
                fiberhostchannel = new Fiberhostchannel();
                fiberhostchannel.setFiberhostid(fiberhoststatus.getFiberhostid());
                //查出数据库配置的测温主机的所有通道
                List<Fiberhostchannel> list2 = fiberhostchannelService.selectFiberhostchannelList(fiberhostchannel);
                int channel1addr = 21; //21表示通道信息的寄存器从21开始，一共有8个寄存器（每个通道）
                for (Fiberhostchannel fiberhostchannel : list2) {
                    short[] shorts2 = new short[8];
                    //默认读取数据时的通道与地址转换关系
                    int channeladdr = channel1addr + (fiberhostchannel.getChannelcode() - 1) * 8;
                    // 读取测温主机的数据
                    shorts2 = modbus4jReader.readHoldingRegister1(modbusMaster, Integer.parseInt(fiberhoststatus.getModbusAddr()), channeladdr, 8);
                    if (shorts2 != null) {

                        fiberhostchannel.setFiberquality(Convert.toInt(shorts2[0]));
                        fiberhostchannel.setPartsum(Convert.toInt(shorts2[1]));
                        fiberhostchannel.setChannellen(Convert.toInt(shorts2[2]));
                        fiberhostchannel.setFirealarm(Convert.toInt(shorts2[3]));
                        fiberhostchannel.setFiberalarm(Convert.toInt(shorts2[4]));
                        Date date = new Date();
                        fiberhostchannel.setDatadate(date);
                        fiberhostchannelService.updateFiberhostchannel(fiberhostchannel);
                    }
                    int partcode1addr = 200; //对应通道下的分区信息的寄存器从200开始
                    //遍历测温主机通道下的分区（partSum为分区数量）
                    for (int i = 1; i <= fiberhostchannel.getPartsum(); i++) {
                        fiberhostpart = new Fiberhostpart();
                        fiberhostpart.setChannelid(fiberhostchannel.getChannelcode());
                        fiberhostpart.setPartcode(i);
                        List<Fiberhostpart> list3 = fiberhostpartService.selectFiberhostpartList(fiberhostpart);
                        short[] shorts3 = new short[8];
                        // 通道下的各个分区与寄存器地址的转换（partcodeaddr为通道下的分区寄存器地址）
                        int partcodeaddr = (fiberhostchannel.getChannelcode() - 1) * 1000 + partcode1addr + (i - 1) * 8;
                        shorts3 = modbus4jReader.readHoldingRegister1(modbusMaster, Integer.parseInt(fiberhoststatus.getModbusAddr()), partcodeaddr, 8);
                        fiberhostparthistory = new Fiberhostparthistory();
                        //更新光纤测温主机每个分区信息(通过)
                        if (list3.size() > 0) {
                            Fiberhostpart fiberhostpart = list3.get(0);
                            Float lstempmax = fiberhostpart.getTempmax();
                            if (shorts3 != null) {
                                fiberhostpart.setAlarmstatus(Convert.toInt(shorts3[0]));//报警状态(0-无报警1-定温2-差温-3预报警)
                                fiberhostpart.setAlarmvalue(Convert.toFloat((shorts3[1] * 0.01 - 200) > 0 ? (shorts3[1] * 0.01 - 200) : 0));//报警阈值(对应报警状态)
                                fiberhostpart.setAlarmloc(Convert.toFloat(shorts3[2]));//报警位置（对应米标）
                                fiberhostpart.setTempmax(Convert.toFloat((shorts3[3] * 0.01 - 200) > 0 ? (shorts3[3] * 0.01 - 200) : 0));//实时最高温度
                                fiberhostpart.setTempmaxloc(Convert.toFloat(shorts3[4]));//实时最高温度位置
                                fiberhostpart.setTempavg(Convert.toFloat((shorts3[5] * 0.01 - 200) > 0 ? (shorts3[5] * 0.01 - 200) : 0));//实时分区平均值
                                Date date = new Date();
                                fiberhostpart.setDatadate(date);
                                fiberhostpartService.updateFiberhostpart(fiberhostpart);

                                if (Math.abs(lstempmax - fiberhostpart.getTempmax()) > 2) {
                                    fiberhostparthistory.setCompanyname("");
                                    fiberhostparthistory.setId(fiberhostchannel.getId());
                                    fiberhostparthistory.setStopfilename(fiberhostchannel.getStopfilename());
                                    fiberhostparthistory.setHostname(fiberhoststatus.getHostname());
                                    fiberhostparthistory.setHostIp(fiberhoststatus.getHostIp());
                                    fiberhostparthistory.setHostport(fiberhoststatus.getHostport());
                                    fiberhostparthistory.setChannelcode(fiberhostchannel.getChannelcode());
                                    fiberhostparthistory.setPartcode(fiberhostpart.getPartcode());
                                    fiberhostparthistory.setAlarmstatus(fiberhostpart.getAlarmstatus());
                                    fiberhostparthistory.setAlarmvalue(fiberhostpart.getAlarmvalue());
                                    fiberhostparthistory.setAlarmloc(fiberhostpart.getAlarmloc());
                                    fiberhostparthistory.setTempmax(fiberhostpart.getTempmax());
                                    fiberhostparthistory.setTempmaxloc(fiberhostpart.getTempmaxloc());
                                    fiberhostparthistory.setTempavg(fiberhostpart.getTempavg());
                                    fiberhostparthistory.setDatadate(new Date());
                                    fiberhostparthistoryService.insertFiberhostparthistory(fiberhostparthistory);
                                }
                            }
                        } else {
                            Fiberhostpart fiberhostpart = new Fiberhostpart();
                            if (shorts3 != null) {
                                fiberhostpart.setChannelid(fiberhostchannel.getChannelid());
                                fiberhostpart.setPartcode(i);
                                fiberhostpart.setAlarmstatus(Convert.toInt(shorts3[0]));
                                fiberhostpart.setAlarmvalue(Convert.toFloat((shorts3[1] * 0.01 - 200) > 0 ? (shorts3[1] * 0.01 - 200) : 0));
                                fiberhostpart.setAlarmloc(Convert.toFloat(shorts3[2]));
                                fiberhostpart.setTempmax(Convert.toFloat((shorts3[3] * 0.01 - 200) > 0 ? (shorts3[3] * 0.01 - 200) : 0));
                                fiberhostpart.setTempmaxloc(Convert.toFloat(shorts3[4]));
                                fiberhostpart.setTempavg(Convert.toFloat((shorts3[5] * 0.01 - 200) > 0 ? (shorts3[5] * 0.01 - 200) : 0));
                                Date date = new Date();
                                fiberhostpart.setDatadate(date);
                                fiberhostpartService.insertFiberhostpart(fiberhostpart);

                                fiberhostparthistory.setCompanyname("");
                                fiberhostparthistory.setId(fiberhostchannel.getId());
                                fiberhostparthistory.setStopfilename(fiberhostchannel.getStopfilename());
                                fiberhostparthistory.setHostname(fiberhoststatus.getHostname());
                                fiberhostparthistory.setHostIp(fiberhoststatus.getHostIp());
                                fiberhostparthistory.setHostport(fiberhoststatus.getHostport());
                                fiberhostparthistory.setChannelcode(fiberhostchannel.getChannelcode());
                                fiberhostparthistory.setPartcode(fiberhostpart.getPartcode());
                                fiberhostparthistory.setAlarmstatus(fiberhostpart.getAlarmstatus());
                                fiberhostparthistory.setAlarmvalue(fiberhostpart.getAlarmvalue());
                                fiberhostparthistory.setAlarmloc(fiberhostpart.getAlarmloc());
                                fiberhostparthistory.setTempmax(fiberhostpart.getTempmax());
                                fiberhostparthistory.setTempmaxloc(fiberhostpart.getTempmaxloc());
                                fiberhostparthistory.setTempavg(fiberhostpart.getTempavg());
                                fiberhostparthistory.setDatadate(new Date());
                                fiberhostparthistoryService.insertFiberhostparthistory(fiberhostparthistory);
                            }
                        }
                        //这是打开球阀的逻辑
                        if (shorts3 != null) {
                            if (Convert.toFloat(shorts3[3] * 0.01 - 200) > Tempmax) {
                                //应该打开光纤通道分区对应分区的球阀
                                //第一步，找见光纤通道对应的球阀modbus主机地址fiberhostchannel.getId()(安装位置的id)
                                Ballvalveaddr ballvalveaddr = ballvalveaddrService.selectBallvalveByPartcode(fiberhostchannel.getId(), i);
                                if (ballvalveaddr != null) {
                                    ballvalveaddr.setFunctioncode(6);
                                    ballvalveaddr.setDataarea("11");
                                    Date date = new Date();
                                    ballvalveaddr.setDatadate(date);
                                    ballvalveaddrService.updateBallvalveaddr(ballvalveaddr);
                                }
                            }
                        }
                    }
                }

            } catch (Exception e) {
                log.error("{}测温主机异常",fiberhoststatus.getHostIp());

            }finally {
                //关闭modbus连接
                if (modbusMaster != null) {
                    modbusMaster.setConnected(false);
                    modbusMaster.destroy();
                }

            }
        }

    }

}
